﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Xml.Linq;
using System.Xml.Schema;
using System.Xml.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace MailRuWrapper.Server
{
    [JsonObject(Id = "User", MemberSerialization = MemberSerialization.OptIn)]
    [DataContract(Name = "User")]
    public class User : IUser
    {
        #region Implementation of IUser

        [JsonProperty("uid")]
        [DataMember(Name = "uid")]
        public string Uid { get; private set; }

        [JsonProperty("first_name")]
        [DataMember(Name = "first_name")]
        public string FirstName { get; private set; }

        [JsonProperty("last_name")]
        [DataMember(Name = "last_name")]
        public string LastName { get; private set; }

        [JsonProperty("nick")]
        [DataMember(Name = "nick")]
        public string Nick { get; private set; }

        [JsonProperty("sex")]
        [DataMember(Name = "sex")]
        public Gender Sex { get; private set; }

        [JsonProperty("birthday")]
        [JsonConverter(typeof(DateTimeConverter))]
        [DataMember(Name = "birthday")]
        public DateTime Birthday { get; private set; }

        [JsonProperty("pic")]
        [DataMember(Name = "pic")]
        public Uri Pic { get; private set; }

        [JsonProperty("pic_small")]
        [DataMember(Name = "pic_small")]
        public Uri PicSmall { get; private set; }

        [JsonProperty("pic_big")]
        [DataMember(Name = "pic_big")]
        public Uri PicBig { get; private set; }

        [JsonProperty("link")]
        [DataMember(Name = "link")]
        public Uri Link { get; private set; }
        
        [JsonProperty("referer_type")]
        [JsonConverter(typeof(RefererConverter))]
        [DataMember(Name = "referer_type")]
        public RefererTypes RefererType { get; private set; }

        [JsonProperty("referer_id")]
        [DataMember(Name = "referer_id")]
        public string RefererId { get; private set; }


        public Uri StatusAgent { get { return new Uri(this.StatusAgent()); } }

        public string MailAdress { get { return this.MailAddress(); } }

        public string FullName
        {
            get { return FirstName + " " + LastName; }
        }

        public bool IsReferred
        {
            get { return RefererType.IsReferred(); }
        }

        #endregion

        internal static IUser Parse(JToken jObject)
        {
            if (jObject.Type == JTokenType.Object)
            {
                var _serializer = new JsonSerializer();
                var _result = _serializer.Deserialize(new JTokenReader(jObject), typeof(User)) as User;
                return _result;
            }
            if (jObject.Type == JTokenType.String)
            {
                return new User { Uid = jObject.Value<string>() };
            }
            return null;
        }

        internal static IUser Parse(XElement element)
        {
            if (element.HasElements)
            {
                var _result = new User
                                  {
                                      Uid = element.Element("uid").Value,
                                      Birthday = element.Element("birthday").Value.ToDateTime(),
                                      FirstName = element.Element("first_name").Value,
                                      LastName = element.Element("last_name").Value,
                                      Link = element.Element("link").Value.ToUri(),
                                      Nick = element.Element("nick").Value,
                                      Pic = element.Element("pic").Value.ToUri(),
                                      PicBig = element.Element("pic_big").Value.ToUri(),
                                      PicSmall = element.Element("pic_small").Value.ToUri(),
                                      Sex = (Gender) element.Element("sex").Value.ToInt(),
                                      RefererType = element.Element("referer_type").Value.ToRefererType(),
                                      RefererId = element.Element("referer_id").Value
                                  };

                return _result;
            }

            return new User {Uid = element.Value};
        }
    }

    [JsonObject(Id = "PhotoAlbum", MemberSerialization = MemberSerialization.OptIn)]
    [DataContract(Name = "PhotoAlbum")]
    public class PhotoAlbum : IPhotoAlbum
    {
        #region Implementation of IPhotoAlbum

        [JsonProperty("aid")]
        [DataMember(Name = "aid")]
        public string Aid { get; private set; }

        [JsonProperty("cover_pid")]
        [DataMember(Name = "cover_pid")]
        public string CoverPid { get; private set; }

        [JsonProperty("owner")]
        [DataMember(Name = "owner")]
        public string Owner { get; private set; }

        [JsonProperty("title")]
        [DataMember(Name = "title")]
        public string Title { get; private set; }

        [JsonProperty("description")]
        [DataMember(Name = "description")]
        public string Description { get; private set; }

        [JsonProperty("created")]
        [JsonConverter(typeof(DateTimeConverter))]
        [DataMember(Name = "created")]
        public DateTime Created { get; private set; }

        [JsonProperty("updated")]
        [JsonConverter(typeof(DateTimeConverter))]
        [DataMember(Name = "updated")]
        public DateTime Updated { get; private set; }

        [JsonProperty("size")]
        [DataMember(Name = "size")]
        public int Size { get; private set; }

        [JsonProperty("privacy")]
        [DataMember(Name = "privacy")]
        public Privacy Privacy { get; private set; }

        #endregion

        public static IPhotoAlbum Parse(JToken jObject)
        {
            var _serializer = new JsonSerializer();
            var _result = _serializer.Deserialize(new JTokenReader(jObject), typeof(PhotoAlbum)) as PhotoAlbum;
            return _result;
        }

        public static IPhotoAlbum Parse(XElement element)
        {
            var _result = new PhotoAlbum
                              {
                                  Aid = element.Element("aid").Value,
                                  CoverPid = element.Element("cover_pid").Value,
                                  Created = element.Element("created").Value.ToDateTime(),
                                  Description = element.Element("description").Value,
                                  Owner = element.Element("owner").Value,
                                  Privacy = (Privacy)element.Element("privacy").Value.ToInt(),
                                  Size = element.Element("size").Value.ToInt(),
                                  Title = element.Element("title").Value,
                                  Updated = element.Element("updated").Value.ToDateTime()
                              };
            return _result;
        }
    }

    [JsonObject(Id = "Photo", MemberSerialization = MemberSerialization.OptIn)]
    [DataContract(Name = "Photo")]
    public class Photo : IPhoto
    {
        #region Implementation of IPhoto

        [JsonProperty("pid")]
        [DataMember(Name = "pid")]
        public string Pid { get; private set; }

        [JsonProperty("aid")]
        [DataMember(Name = "aid")]
        public string Aid { get; private set; }

        [JsonProperty("owner")]
        [DataMember(Name = "owner")]
        public string Owner { get; private set; }

        [JsonProperty("src")]
        [DataMember(Name = "src")]
        public Uri Src { get; private set; }

        [JsonProperty("src_small")]
        [DataMember(Name = "src_small")]
        public Uri SrcSmall { get; private set; }

        [JsonProperty("src_big")]
        [DataMember(Name = "src_big")]
        public Uri SrcBig { get; private set; }

        [JsonProperty("created")]
        [JsonConverter(typeof(DateTimeConverter))]
        [DataMember(Name = "created")]
        public DateTime Created { get; private set; }

        [JsonProperty("width")]
        [DataMember(Name = "width")]
        public int Width { get; private set; }

        [JsonProperty("height")]
        [DataMember(Name = "height")]
        public int Height { get; private set; }

        [JsonProperty("size")]
        [DataMember(Name = "size")]
        public int Size { get; private set; }

        [JsonProperty("title")]
        [DataMember(Name = "title")]
        public string Title { get; private set; }

        #endregion

        public static IPhoto Parse(JToken jObject)
        {
            var _serializer = new JsonSerializer();
            var _result = _serializer.Deserialize(new JTokenReader(jObject), typeof(Photo)) as Photo;
            return _result;
        }

        public static IPhoto Parse(XElement element)
        {
            var _result = new Photo
            {
                Aid = element.Element("aid").Value,
                Created = element.Element("created").Value.ToDateTime(),
                Owner = element.Element("owner").Value,
                Size = element.Element("size").Value.ToInt(),
                Title = element.Element("title").Value,
                Height = element.Element("height").Value.ToInt(),
                Pid = element.Element("pid").Value,
                Src = element.Element("src").Value.ToUri(),
                SrcBig = element.Element("src_big").Value.ToUri(),
                SrcSmall = element.Element("src_small").Value.ToUri(),
                Width = element.Element("width").Value.ToInt(),
            };
            return _result;
        }
    }

    [JsonObject(Id = "Audio", MemberSerialization = MemberSerialization.OptIn)]
    [DataContract(Name = "Audio")]
    public class Audio : IAudio
    {
        #region Implementation of IAudio
        [JsonProperty("mid")]
        [DataMember(Name = "mid")]
        public string Mid { get; private set; }
        [JsonProperty("owner")]
        [DataMember(Name = "owner")]
        public string Owner { get; private set; }
        [JsonProperty("artist")]
        [DataMember(Name = "artist")]
        public string Artist { get; private set; }
        [JsonProperty("title")]
        [DataMember(Name = "title")]
        public string Title { get; private set; }
        [JsonProperty("duration")]
        [DataMember(Name = "duration")]
        public int Duration { get; private set; }
        [JsonProperty("size")]
        [DataMember(Name = "size")]
        public int Size { get; private set; }
        [JsonProperty("created")]
        [JsonConverter(typeof(DateTimeConverter))]
        [DataMember(Name = "created")]
        public DateTime Created { get; private set; }
        [JsonProperty("link")]
        [DataMember(Name = "link")]
        public Uri Link { get; private set; }

        #endregion

        public static IAudio Parse(JToken jObject)
        {
            var _serializer = new JsonSerializer();
            var _result = _serializer.Deserialize(new JTokenReader(jObject), typeof(Audio)) as Audio;
            return _result;
        }

        public static IAudio Parse(XElement element)
        {
            var _result = new Audio
            {
                Created = element.Element("created").Value.ToDateTime(),
                Owner = element.Element("owner").Value,
                Size = element.Element("size").Value.ToInt(),
                Title = element.Element("title").Value,
                Artist = element.Element("artist").Value,
                Duration = element.Element("duration").Value.ToInt(),
                Link = element.Element("link").Value.ToUri(),
                Mid = element.Element("mid").Value
            };
            return _result;
        }
    }
}
